import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Random;

public class AI extends Player{

	public AI(String name, int battleWinnings, Pet activePet, ArrayList<Pet> petList, Difficulty difficulty) {
		
		super(name, battleWinnings, 0, activePet, null, difficulty, 0);

		
		playerName = name;
		money = battleWinnings;
		this.activePet = activePet;
		inventory = new Inventory();
		passivePetList = petList;
		
		if (passivePetList != null){
			swapPassivePet();
		}
/*
Debug: skriver ut vad ai:n byter till i listan.
		if (passivePet != null && passivePetList != null){
			swapPassivePet();
			System.out.println("Har bytt till : " + passivePet.getName());
		}

*/
	}
	
	public AI copy() {
		ArrayList<Pet> bossPassives = new ArrayList<Pet>(passivePetList);
		bossPassives.add(passivePet);
		AI duplicate = new AI(playerName, money, activePet.copy(), bossPassives, difficulty);
		return duplicate;
	}
	
	public ArrayList<Pet> passivePetList = new ArrayList<Pet>();

	public int turnNo = 0;
	public int chosenAttack = 0;
	private Action nextAction;
	public int check;
	
	public void swapPassivePet(){
		
		if (passivePetList.size() != 0){
			if (passivePet != null) {
				passivePetList.add(passivePet);
			}
			passivePet = passivePetList.get(0);
			passivePetList.remove(0);
		}
		
	}
	
	public int getLivingPets(){
		int fiendePetCount = 0;
		
		if (activePet.damageTaken < activePet.getMaxHealth()) {
			fiendePetCount++;
		}
		if (passivePet != null && passivePet.damageTaken < passivePet.getMaxHealth()) {
			fiendePetCount++;
		}
		for (Pet pet : passivePetList) {
			if (pet.damageTaken < pet.getMaxHealth()) {
				fiendePetCount++;
			}
		}
		return fiendePetCount;
	}
	
	public void addPetToList(Pet addPet){
		
		if (passivePet == null){
			passivePet = addPet;
		}
		else {
			passivePetList.add(addPet);
		}
	}
	
	private AttackName getUlti() {
		Attack currentUlti = new Attack(activePet.attacks.get(0)); 
		for (AttackName atkN : activePet.attacks) {
			Attack atk = new Attack(atkN);
			if (atk.energyCost > currentUlti.energyCost && atk.skill == "attack")
				currentUlti = atk;
		}
		
		return currentUlti.getAtkName();
	}
	
	private AttackName statsManip(){
		Attack useStats = new Attack(activePet.attacks.get(0)); 
		for (AttackName atkN : activePet.attacks) {
			Attack atk = new Attack(atkN);
		if(atk.skill == "stats")
			useStats = atk;
		}
		return useStats.getAtkName();
	}
	
	private AttackName getLeastEnergyCost() {
		Attack currentLeast = new Attack(activePet.attacks.get(0)); 
		for (AttackName atkN : activePet.attacks) {
			Attack atk = new Attack(atkN);
			if (atk.energyCost < currentLeast.energyCost && atk.skill == "attack")
				currentLeast = atk;
		}
		
		return currentLeast.getAtkName();
	}
	
	private AttackName getMostEffective() {
		Attack currentEffective = new Attack(activePet.attacks.get(0));
		double currentEffectivity = (double) currentEffective.effects.amount/currentEffective.energyCost;
		for (AttackName atkN : activePet.attacks) {
			Attack atk = new Attack(atkN);
			double efty = (double) atk.effects.amount/atk.energyCost;
			if (efty > currentEffectivity  && atk.skill == "attack") {
				currentEffective = atk;
				currentEffectivity = efty;
			}
		}
		
		return currentEffective.getAtkName();
	}
	
	private ItemKind getStrongestPotion(int maxheal) {
		ArrayList<ItemKind> healingItems = new ArrayList<ItemKind>(new LinkedHashSet<ItemKind>());
		for (ItemKind ik : inventory.getEffectItems()) {
			Item item = new Item(ik);
			if (item.effect.type == EffectType.AddHealth && item.effect.relativeTarget == Target.Self) {
				healingItems.add(item.getKind());
			}
		}
		
		if (healingItems.size() == 0) {
			return null;
		}
		Item strongest = new Item(healingItems.get(0));
		for (ItemKind ik : healingItems) {
			Item item = new Item(ik);
			if (item.effect.amount < maxheal &&
					item.effect.amount > strongest.effect.amount) {
				strongest = item;
			}
		}
		
		return strongest.getKind();
	}

	
	//Om referensen Ã¤r bra/neutral emot target
	//lol
	private boolean isCounter(Pet reference, Pet target){
		
		switch (reference.element){
			case Fire:{
				if (target.element == Type.Water){
					return true;
				}
				else {
					return false;
				}
			}
			case Water:{
				if (target.element == Type.Energy){
					return true;
				}
				else {
					return false;
				}
				
			}
			case Nature:{
				if (target.element == Type.Fire){
					return true;
				}
				else {
					return false;
				}
				
			}
			case Energy:{
				if (target.element == Type.Nature){
						return true;
					}
				else {
					return false;
				}
			}
		case Stats:
			break;
		default:
			break;
		}
		return false;
	}
	
	/*
	 * TODO:
	 * Stat       getWeakness(Pet enemyPet)
	 *            -- vad den nu ska gÃ¶ra
	 */
	
	public Action doSomething(Pet enemyPet, Difficulty difficulty, boolean catchAble) {
		    /*
		     *  TODO: Denna ska anropas varje frame,
			 *  och det Ã¤r i denna som fienden fattar
			 *  beslut baserat pÃ¥ stuff den vet.
			 *  
			 *  Feel free att lÃ¤gga till flera fÃ¤lt till klassen
			 *  som kan innehÃ¥lla dess "kunskap" om hur striden
			 *  gÃ¥r.
			 *  
			 *  Funktionen returnerar en Action som TurnHandlern
			 *  fÃ¥r ta hand om senare. 
			 */
		
		turnNo++;
		chosenAttack = 0;
		check = 0;
		fightToTheLastPet(); //! >:O	


		
		
		if (turnNo%60 == 0){
			
			
				if (passivePet != null){
					Action message = counterPet(enemyPet);
					if (message != null){
						return message;
					}
				}

				
				if (activePet.getCurrentHealth() < activePet.getMaxHealth()*0.4 
						&& getStrongestPotion((int) (activePet.getMaxHealth()*0.4)) != null && activePet.energy > 10){
					if (!catchAble){
						nextAction = new UseItem(getStrongestPotion((int) (activePet.getMaxHealth()*0.4)));
						return nextAction;
					}
				}
				Random r = new Random();
				int randomInt = r.nextInt(100) + 1;
				
				if(randomInt < 15 && activePet.getMaxHealth() >= 0.8 && enemyPet.getMaxHealth() >= 0.8){
						nextAction = new UseAttack(statsManip());
						return nextAction;
					}
				
				if (enemyPet.getCurrentHealth() > 0.9*enemyPet.getMaxHealth()){
					
					nextAction = new UseAttack(getUlti());
					return nextAction;
				}
				
				else if (enemyPet.getCurrentHealth() > 0.4*enemyPet.getCurrentHealth() && turnNo%360 == 0){

					nextAction = new UseAttack(getMostEffective());
					return nextAction;
				}
				
				else if (enemyPet.getCurrentHealth() > 0){
					
					nextAction = new UseAttack(getLeastEnergyCost());
					return nextAction;
				}

				}
				
			
		
		return null;
	}

	public SwapPet counterPet(Pet enemyPet){
		
		int counter = 0;
		
		if (isCounter(activePet, enemyPet)){
			if (!isCounter(passivePet, enemyPet) && passivePet.isAlive()){
				return new SwapPet();
			}
			for (Pet pet : passivePetList){
				if (!isCounter(pet, enemyPet) && pet.isAlive()){
					passivePetList.add(passivePet);
					passivePet = passivePetList.get(counter);
					passivePetList.remove(counter);
					return new SwapPet();
				}
				counter++;
			}	
		}
		return null;
	}
	
	public void fightToTheLastPet(){
		
		/*
		 * check kollar om den redan har gått igenom listan
		 * 
		 * sen letar den efter ett passive pet med hälsa != 0
		 * 
		 * annars lägg på +1 på check och testa igen
		 */
		
		if (check != passivePetList.size()){
			if (passivePet.getCurrentHealth() == 0){
				swapPassivePet();
				check++;
				fightToTheLastPet();
			}
		}	
	}
}
